package com.wispx.gateway.bootstrap;

import com.wispx.gateway.config.config.Config;
import com.wispx.gateway.config.loader.ConfigLoader;
import com.wispx.gateway.config.manager.DynamicConfigManager;
import com.wispx.gateway.config.pojo.RouteDefinition;
import com.wispx.gateway.config.pojo.ServiceDefinition;
import com.wispx.gateway.config.pojo.ServiceInstance;
import com.wispx.gateway.config.service.ConfigCenterProcessor;
import com.wispx.gateway.config.service.RouteChangeListener;
import com.wispx.gateway.core.container.Container;
import com.wispx.gateway.register.service.RegisterCenterListener;
import com.wispx.gateway.register.service.RegisterCenterProcessor;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.ServiceLoader;
import java.util.Set;

@Slf4j
public class GatewayBootstrap {

    private Config config;
    private Container container;

    public static void run(String[] args) {
        new GatewayBootstrap().start(args);
    }

    public void start(String[] args) {
        log.info("gateway bootstrap start");

        // 加载配置
        config = ConfigLoader.loadConfig(args);
        log.info("gateway bootstrap successfully load config:{}", config);

        // 初始化配置中心
        initConfigCenter();

        // 初始化容器
        initContainer();
        container.start();

        // 初始化注册中心
        initRegisterCenter();

        // 注册钩子
        registerShutdownHook();
    }

    private void initConfigCenter() {
        // spi 加载配置中心处理器
        ConfigCenterProcessor configCenterProcessor = ServiceLoader.load(ConfigCenterProcessor.class).findFirst().orElseThrow(() -> {
            throw new RuntimeException("not found configCenterProcessor impl");
        });
        configCenterProcessor.init(config.getConfigCenter());
        configCenterProcessor.subscribeConfigChange(new RouteChangeListener() {
            @Override
            public void routeOnChange(List<RouteDefinition> newRoutes) {
                // 更新本地缓存的配置
                DynamicConfigManager.getInstance().updateRoutes(newRoutes, true);
                // 回调已添加的监听器（可能监听器很多，需要这个监听器执行时，去执行其他已添加的监听器）
                for (RouteDefinition newRoute : newRoutes) {
                    DynamicConfigManager.getInstance().changeRoute(newRoute);
                }
            }
        });
    }

    private void initContainer() {
        container = new Container(config);
    }

    private void initRegisterCenter() {
        RegisterCenterProcessor registerCenterProcessor = ServiceLoader.load(RegisterCenterProcessor.class).findFirst().orElseThrow(() -> {
            throw new RuntimeException("not find registerCenterProcessor impl");
        });
        registerCenterProcessor.init(config);
        registerCenterProcessor.subscribeServiceChange(new RegisterCenterListener() {
            @Override
            public void whenInstanceChange(ServiceDefinition serviceDefinition, Set<ServiceInstance> serviceInstances) {
                // 服务下的实例变化时，更新本地缓存的 ServiceDefinition、ServiceInstance
                DynamicConfigManager.getInstance().updateService(serviceDefinition);
                DynamicConfigManager.getInstance().updateServiceInstance(serviceDefinition, serviceInstances);
            }
        });

    }

    private void registerShutdownHook() {
        // JVM 关闭时调用
        Runtime.getRuntime().addShutdownHook(new Thread(() -> container.shutdown()));
    }

}
